package store.lunangangster.engine;

import java.io.InputStream;
import javax.sql.DataSource;
import org.apache.ibatis.transaction.TransactionFactory;
import org.springframework.core.io.Resource;
import store.lunangangster.engine.bpmn.parser.BpmnParsers;
import store.lunangangster.engine.impl.agenda.NodeFlowEngineAgendaFactory;
import store.lunangangster.engine.impl.calendar.DefaultCalendarManager;
import store.lunangangster.engine.impl.cmd.CommandExecutor;
import store.lunangangster.engine.impl.config.SpringBeanDefinitionResolver;
import store.lunangangster.engine.impl.db.DbSqlSessionFactory;
import store.lunangangster.engine.impl.db.cache.EntityCacheSessionFactory;
import store.lunangangster.engine.impl.el.ExpressManager;
import store.lunangangster.engine.impl.entity.mgr.ByteArrayManager;
import store.lunangangster.engine.impl.entity.mgr.DeploymentEntityManager;
import store.lunangangster.engine.impl.entity.mgr.DeploymentManager;
import store.lunangangster.engine.impl.entity.mgr.ExecutionEntityManager;
import store.lunangangster.engine.impl.entity.mgr.HistoryEntityManager;
import store.lunangangster.engine.impl.entity.mgr.HistoryManager;
import store.lunangangster.engine.impl.entity.mgr.IdentityLinkEntityManager;
import store.lunangangster.engine.impl.entity.mgr.MesListenerEntityManager;
import store.lunangangster.engine.impl.entity.mgr.ProcessDefinitionEntityManager;
import store.lunangangster.engine.impl.entity.mgr.ResourceEntityManager;
import store.lunangangster.engine.impl.entity.mgr.TaskEntityManager;
import store.lunangangster.engine.impl.entity.mgr.VariableEntityManager;
import store.lunangangster.engine.impl.helper.ProcessInstanceHelper;
import store.lunangangster.engine.impl.repository.BpmnDeployer;
import store.lunangangster.engine.impl.repository.DeployCacheManager;
import store.lunangangster.engine.impl.repository.DeploymentCache;
import store.lunangangster.engine.impl.repository.DeploymentParseBuilderFactory;
import store.lunangangster.engine.impl.repository.ProcessDefinitionCacheEntry;
import store.lunangangster.engine.service.HistoryService;
import store.lunangangster.engine.service.RepositoryService;
import store.lunangangster.engine.service.RuntimeService;
import store.lunangangster.engine.service.TaskService;

public abstract class ProcessEngineConfiguration {

  protected static final String DEFAULT_BEAN_NAME = "processEngineConfiguration";
  protected static final String DEFAULT_CFG_PATH = "nodeflow.cfg.xml";

  protected String name;
  protected String path;
  protected String jdbcUsername;
  protected String jdbcPassword;
  protected String jdbcDriverName;
  protected String jdbcUrl;
  protected DataSource dataSource;

  // ProcessEngine
  public abstract ProcessEngine buildEngine();

  // Service
  public abstract RepositoryService getRepositoryService();
  public abstract RuntimeService getRuntimeService();
  public abstract TaskService getTaskService();
  public abstract HistoryService getHistoryService();

  // Manager
  public abstract DeploymentEntityManager getDeploymentEntityManager();
  public abstract ResourceEntityManager getResourceEntityManager();
  public abstract ProcessDefinitionEntityManager getProcessDefinitionEntityManager();
  public abstract ExecutionEntityManager getExecutionEntityManager();
  public abstract TaskEntityManager getTaskEntityManager();
  public abstract IdentityLinkEntityManager getIdentityLinkEntityManager();
  public abstract VariableEntityManager getVariableEntityManager();
  public abstract MesListenerEntityManager getMesListenerEntityManager();
  public abstract HistoryEntityManager getHistoryEntityManager();
  public abstract ByteArrayManager getByteArrayManager();

  // Helper
  public abstract ProcessInstanceHelper getProcessInstanceHelper();

  // Manager
  public abstract DeploymentManager getDeploymentManager();
  public abstract DeployCacheManager getDeployCacheManager();
  public abstract HistoryManager getHistoryManager();
  public abstract ExpressManager getExpressManager();
  public abstract DeploymentCache<ProcessDefinitionCacheEntry> getDeploymentCache();
  public abstract DefaultCalendarManager getCalendarManager();

  // Bpmn
  public abstract BpmnDeployer getBpmnDeployer();
  public abstract DeploymentParseBuilderFactory getDeploymentParseBuilderFactory();
  public abstract BpmnParsers getBpmnParser();

  // Factory
  public abstract TransactionFactory getTransactionFactory();
  public abstract EntityCacheSessionFactory getEntityCacheSessionFactory();
  public abstract DbSqlSessionFactory getDbSqlSessionFactory();
  public abstract NodeFlowEngineAgendaFactory getAgendaFactory();

  // System
  public abstract EngineClock getEngineClock();

  // CommandExecutor
  public abstract CommandExecutor getCommandExecutor();


  public static ProcessEngineConfiguration createDefaultConfiguration() {
    return createConfigurationFromResourcePath(DEFAULT_CFG_PATH, DEFAULT_BEAN_NAME);
  }

  public static ProcessEngineConfiguration createDefaultConfiguration(String beanName) {
    return createConfigurationFromResourcePath(DEFAULT_CFG_PATH, beanName);
  }

  public static ProcessEngineConfiguration createConfigurationFromInputStream(InputStream is) {
    return createConfigurationFromInputStream(is, DEFAULT_BEAN_NAME);
  }

  public static ProcessEngineConfiguration createConfigurationFromInputStream(InputStream is, String beanName) {
    return SpringBeanDefinitionResolver.resolveProcessEngineConfiguration(is, beanName);
  }

  public static ProcessEngineConfiguration createConfigurationFromResourcePath(String resourcePath) {
    return createConfigurationFromResourcePath(resourcePath, DEFAULT_BEAN_NAME);
  }

  public static ProcessEngineConfiguration createConfigurationFromResourcePath(String resourcePath, String beanName) {
    return SpringBeanDefinitionResolver.resolveProcessEngineConfiguration(resourcePath, beanName);
  }

  public static ProcessEngineConfiguration createConfigurationFromResource(Resource resource) {
    return createConfigurationFromResource(resource, DEFAULT_BEAN_NAME);
  }

  public static ProcessEngineConfiguration createConfigurationFromResource(Resource resource, String beanName) {
    return SpringBeanDefinitionResolver.resolveProcessEngineConfiguration(resource, beanName);
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getPath() {
    return path;
  }

  public void setPath(String path) {
    this.path = path;
  }

  public String getJdbcUsername() {
    return jdbcUsername;
  }

  public void setJdbcUsername(String jdbcUsername) {
    this.jdbcUsername = jdbcUsername;
  }

  public String getJdbcPassword() {
    return jdbcPassword;
  }

  public void setJdbcPassword(String jdbcPassword) {
    this.jdbcPassword = jdbcPassword;
  }

  public String getJdbcDriverName() {
    return jdbcDriverName;
  }

  public void setJdbcDriverName(String jdbcDriverName) {
    this.jdbcDriverName = jdbcDriverName;
  }

  public String getJdbcUrl() {
    return jdbcUrl;
  }

  public void setJdbcUrl(String jdbcUrl) {
    this.jdbcUrl = jdbcUrl;
  }

  public DataSource getDataSource() {
    return dataSource;
  }

  public void setDataSource(DataSource dataSource) {
    this.dataSource = dataSource;
  }

}
